<template>
  <!-- 新增部门的弹层 -->
  <!-- 触发关闭弹出框的close事件，也要调用弹出框中的取消按钮的btnCancel事件 -->
  <el-dialog :title="formData.id?'编辑部门':'新增部门'" :visible="showDialog" @close="btnCancel">
    <!-- 表单组件  el-form   label-width设置label的宽度   -->
    <!-- 匿名插槽 -->
    <el-form ref="addDept" label-width="120px" :model="formData" :rules="rules">
      <el-form-item label="部门名称" prop="name">
        <el-input v-model="formData.name" style="width:80%" placeholder="1-50个字符" />
      </el-form-item>
      <el-form-item label="部门编码" prop="code">
        <el-input v-model="formData.code" style="width:80%" placeholder="1-50个字符" />
      </el-form-item>
      <el-form-item label="部门负责人" prop="manager">
        <el-select
          v-model="formData.manager"
          style="width:80%"
          placeholder="请选择"
          @focus="getEmployeeSimple"
          @blur="checkManager"
        >
          <el-option v-for="value in employeeList" :key="value.id" :value="value.username" :label="value.username" />
        </el-select>
      </el-form-item>
      <el-form-item label="部门介绍" prop="introduce">
        <el-input v-model="formData.introduce" style="width:80%" placeholder="1-300个字符" type="textarea" :rows="3" />
      </el-form-item>
    </el-form>
    <!-- el-dialog有专门放置底部操作栏的 插槽  具名插槽 -->
    <el-row slot="footer" type="flex" justify="center">
      <!-- 列被分为24 -->
      <el-col :span="6">
        <el-button type="primary" size="small" @click="btnOk">确定</el-button>
        <el-button size="small" @click="btnCancel">取消</el-button>
      </el-col>
    </el-row>
  </el-dialog>
</template>

<script>
import { getDepartment, addDepartment, getDepartmentDetail, editDepartment } from '@/api/departments'
import { getEmployeeSimple } from '@/api/employees'
export default {
  props: {
    showDialog: {
      type: Boolean,
      default: false
    },
    treeNode: {
      type: Object,
      required: true
    }
  },
  data() {
    // 相同名字的校验
    const checkRepeatName = async(rules, value, callback) => {
      // value: 当前输入框中输入的值
      // 同一部门下不能有重名
      // 1. 所有部门列表
      const { depts } = await getDepartment()
      let isRepeat = false
      //   编辑部门与新增部门是不一样的处理，所以要根据回显数据中的id来进行区分
      if (this.formData.id) {
        isRepeat = depts
        // 编辑部门：通过点击当前元素的进行编辑的，要想排除自己在外去筛选相同名字，就需要找到同一个父部门才能进行筛选
        // 当前点击的元素的pid等于遍历元素的pid，就筛选出当前点击元素的父部门
        // 因为不能和自己相比较，所以还需要一个条件，当前点击的元素的id不能等于遍历元素的id
        // 两个条件相加，就能筛选出相同部门下，除自己外的其他元素
        // 在这两个条件下的，再进行名字相同的筛选
          .filter(item => item.pid === this.treeNode.pid && item.id !== this.treeNode.id)
          // 同部门下的其他元素的名字===当前点击元素下填写的名字相同，返回true，不同则返回false
          .some(item => item.name === value)
      } else {
        // 2. 当前被点击作为父部门的那个id
        isRepeat = depts
        //   筛选父部门：新增部门是通过点击父部门元素的，所以需要找到遍历元的相同pid，就能知道大家的父部门，所以当前点击的元素id=遍历元素的pid就可以筛选出父部门
          .filter(item => item.pid === this.treeNode.id)
          // 寻找当前父部门下的部门名字是否有跟当前输入框中相同名字，如果有，返回true，无返回false
          .some(item => item.name === value)
      }

      // 3. 当前用户正在输入的值
      // value
      isRepeat ? callback(new Error('同一部门下不能同名')) : callback()
    }

    // 相同编码的校验
    const checkRepeatCode = async(rules, value, callback) => {
      const { depts } = await getDepartment()
      let isRepeat = false
      if (this.formData.id) {
        // 点击编辑部门，就是需要寻找自己本身外的其他元素是否有相同的编码，需要排除自己在外，所以需要寻找到当前的点击元素的id不能等同于遍历元素的id，这样就能找到除自己外的其他元素，进行编码相同的校验
        isRepeat = depts.some(item => item.code === value && item.id !== this.treeNode.id)
      } else {
        // 2. 在这个depts数组中寻找code 是否与当前输入框中输入的值相同，如果相同，返回true，不相同，返回false
        isRepeat = depts.some(item => item.code === value)
      }
      isRepeat ? callback(new Error('部门编码不能相同')) : callback()
    }
    return {
      formData: {
        name: '',
        code: '',
        introduce: '',
        manager: ''
      },
      rules: {
        name: [
          { required: true, message: '此项不能为空', trigger: 'blur' },
          { min: 1, max: 50, message: '长度在 1 到 50 个字符', trigger: 'blur' },
          { trigger: 'blur', validator: checkRepeatName }
        ],
        code: [
          { required: true, message: '此项不能为空', trigger: 'blur' },
          { min: 1, max: 50, message: '长度在 1 到 50 个字符', trigger: 'blur' },
          { trigger: 'blur', validator: checkRepeatCode }
        ],
        manager: [
          { required: true, message: '此项不能为空', trigger: 'blur' }
        ],
        introduce: [
          { required: true, message: '此项不能为空', trigger: 'blur' },
          { min: 1, max: 300, message: '长度在 1 到 300 个字符', trigger: 'blur' }
        ]
      },
      employeeList: []
    }
  },
  methods: {
    // 点击弹出框中负责人的获取员工列表方法
    async getEmployeeSimple() {
      // 选择框中聚焦，就发送请求，获取员工列表信息，获取到的是一个数组，直接把数据赋值给我们自己定义的employeeList数组中
      this.employeeList = await getEmployeeSimple()
      console.log(this.employeeList)
    },
    // 选择框失焦，触发校验函数：不能为空 处理
    checkManager() {
      // 这是失去焦点的部门负责人, 需要手动触发校验，基本的调用表单验证不能实现非空检验
      // validateField:对部分表单字段进行校验的方法--element-ui表单校验方法
      // 因为此时这个函数时一个失焦函数，而我们点击一个负责人的时候，就会先执行失焦事件，再到点击事件
      // 这个时候，我们需要给这个失焦函数来一个定时器，延长一下这个失焦函数的执行时间，让点击事件先行
      setTimeout(() => {
        this.$refs.addDept.validateField('manager')
      }, 200)
    },
    // 点击弹出框中的确认按钮事件
    async btnOk() {
      // 点击确定前，要进行表单的校验：不能让他们空的就发送请求
      // 如果不添加任何参数，那么就是一个promise对象，我们可以使用await来等待这个表单校验通过之后才执行下面的代码
      await this.$refs.addDept.validate()
      // 根据回显数据来进行分辨 编辑部门 还是 新增部门 功能
      // 回显数据中是有id的，所以可以通过这个id来判断
      // 新增部门与编辑部门的api请求方法是不一样的：所以要分辨开来
      if (this.formData.id) {
        // 编辑部门功能
        await editDepartment(this.formData)
      } else {
        // 新增部门
        // 1.发送请求:发送请求有5个参数，在formData中只有四个参数，还差一个父级id，这个父级id就是我们接收的数据treeNode中的id，因为我们是点击父级的添加子部门来进行添加的，所以我们获取到的treeNode的id就是父级的id
        await addDepartment({ ...this.formData, pid: this.treeNode.id })
      }
      // 提示用户：操作成功
      this.$message.success('添加成功')
      // 成功后关闭弹窗，设置showDialog的属性值为false,这是可以简化子传父的操作，但是要在父组件中使用子组件的位置，传数据的参数后面加一个.sync
      this.$emit('update:showDialog', false)
      // 父传子：进行刷新页面
      this.$emit('addDepartment')
    },
    // 点击取消按钮，实现关闭弹窗处理函数
    btnCancel() {
      // 为了照顾编辑的情况, 每次关闭强制将表单恢复到原样
    //   如果只是调用resetFields，只是会把其中的一些值重置为初始值，点击新增部门的时候，title还是编辑部门，会漏掉很多属性，所以我们直接把formData重置为这四个属性，就不会出错的情况
      this.formData = {
        code: '',
        introduce: '',
        manager: '',
        name: ''
      }
      // 1.实现表单的清空处理：如果第一次点的时候，输入了一些信息，点击关闭的时候，不会清空内容，需要我们手动设置清空表单内容
      // resetFields:对整个表单进行重置，将所有字段值重置为初始值并移除校验结果
      // 先清理表单绑定的数据
      // 清理校验结果:如果第一次有一些选项没有填，会有校验信息提醒，在点击取消按钮之后，也需要把校验信息清理掉
      this.$refs.addDept.resetFields()
      // 2.设置showDialog属性为false
      this.$emit('update:showDialog', false)
    },
    async getDepartmentDetail(id) {
      // 回显数据：就是把获取到的数据，赋值到 我们绑定的表单元素上，也就是formData这个对象中
      this.formData = await getDepartmentDetail(id)
    }

  }
}
</script>

<style>

</style>
